package com.nfc.lock.task;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nfc.lock.common.constant.Constants;
import com.nfc.lock.entity.NfcLock;
import com.nfc.lock.entity.PowerRoom;
import com.nfc.lock.entity.WarningRecord;
import com.nfc.lock.mapper.NfcLockMapper;
import com.nfc.lock.mapper.PowerRoomMapper;
import com.nfc.lock.mapper.WarningRecordMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

/**
 * Scheduled job that creates warning records for locks that remain open too long.
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WarningTask {

    private final NfcLockMapper nfcLockMapper;
    private final PowerRoomMapper powerRoomMapper;
    private final WarningRecordMapper warningRecordMapper;

    /**
     * Runs every hour to detect locks that have been left open beyond the configured threshold.
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void checkLongTimeUnlocked() {
        log.info("Starting scheduled check for long-time unlocked locks");

        try {
            List<NfcLock> locks = nfcLockMapper.selectLongTimeUnlocked(Constants.UNLOCK_WARNING_MINUTES);
            if (locks.isEmpty()) {
                log.info("No locks require attention at this time");
                return;
            }

            log.info("Detected {} locks that exceed the allowed open duration", locks.size());
            int createdCount = 0;

            for (NfcLock lock : locks) {
                LambdaQueryWrapper<WarningRecord> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(WarningRecord::getLockId, lock.getLockId())
                        .eq(WarningRecord::getWarningType, Constants.WarningType.LONG_UNLOCK)
                        .eq(WarningRecord::getStatus, 0);

                Long existing = warningRecordMapper.selectCount(wrapper);
                if (existing != null && existing > 0) {
                    log.debug("Skipping lock {} because an active warning already exists", lock.getLockNfcId());
                    continue;
                }

                PowerRoom room = powerRoomMapper.selectById(lock.getRoomId());

                LocalDateTime now = LocalDateTime.now();
                long minutes = 0;
                if (lock.getLastOperateTime() != null) {
                    minutes = Duration.between(lock.getLastOperateTime(), now).toMinutes();
                }

                WarningRecord warning = new WarningRecord();
                warning.setWarningType(Constants.WarningType.LONG_UNLOCK);
                warning.setLockId(lock.getLockId());
                warning.setRoomId(lock.getRoomId());
                warning.setRoomName(room != null ? room.getRoomName() : "Unknown room");
                warning.setWarningContent(String.format(
                        "Lock %s located in %s has remained open for %d minutes, please investigate.",
                        lock.getLockNfcId(),
                        warning.getRoomName(),
                        minutes
                ));
                warning.setUnlockDuration(minutes);
                warning.setStatus(0);

                warningRecordMapper.insert(warning);
                createdCount++;

                log.warn("Generated warning for lock {} in room {} (open {} minutes)",
                        lock.getLockNfcId(), warning.getRoomName(), minutes);
            }

            log.info("Completed scheduled warning check, created {} warning records", createdCount);

        } catch (Exception e) {
            log.error("Scheduled warning check failed", e);
        }
    }

    /**
     * Helper method to manually trigger the check with a shorter duration during development.
     * Disabled by default in production environments.
     */
    // @Scheduled(cron = "0 */5 * * * ?")
    public void checkLongTimeUnlockedTest() {
        log.info("Manual test: checking for locks open longer than 10 minutes");

        List<NfcLock> locks = nfcLockMapper.selectLongTimeUnlocked(10);
        log.info("Test run found {} locks exceeding 10 minutes", locks.size());

        for (NfcLock lock : locks) {
            PowerRoom room = powerRoomMapper.selectById(lock.getRoomId());
            LocalDateTime now = LocalDateTime.now();
            long minutes = lock.getLastOperateTime() != null
                    ? Duration.between(lock.getLastOperateTime(), now).toMinutes()
                    : 0;

            log.info("  - Lock {} in room {} has been open for {} minutes",
                    lock.getLockNfcId(),
                    room != null ? room.getRoomName() : "Unknown",
                    minutes);
        }
    }
}